package com.jason.shader.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;

import com.jason.shader.R;

/**
 * desc:
 *
 *      matrix.setValue(new float[]{
 *          1, 0, 57,
 *          0, 1, 78,
 *          0, 0, 1
 *      })
 *
 *      // 最后的三个数是用来设置透视变换的,最后的一个值恒为1,为其表示的是在Z轴向的透视缩放
 *      // 这三个值都可以被设置,前两个值跟右手坐标系的XY轴有关系
 *
 *      与 matrix.setTranslate(57,58)的效果是一样的
 *
 *
 *
 * user:jason
 * date:16-9-7
 * time:下午5:00
 */
public class MatrixImageView7 extends ImageView {

    private static final int MODE_NONE = 0x00123; // 默认的触摸模式
    private static final int MODE_DRAG = 0x00321; // 拖拽模式
    private static final int MODE_ZOOM = 0x00132; // 缩放或者旋转

    private int mode ; // 当前的触摸模式

    private float preMove = 1F; // 上一次手指移动的距离
    private float saveRotate = 0F; // 保存的角度值
    private float rotate = 0F; // 旋转的角度

    private float[] preEventCoor; // 上一次各触摸点的坐标集合
    private PointF start, mid; // 起点、中点对象
    private Matrix currentMatrix, savedMatrix; // 当前和保存了的Matrix对象
    private Bitmap imageBitmap;


    public MatrixImageView7(Context context, AttributeSet attrs) {
        super(context, attrs);

        // 初始化
        init();
    }

    private void init() {

        int width = getResources().getDisplayMetrics().widthPixels;
        int height = getResources().getDisplayMetrics().heightPixels;

        currentMatrix = new Matrix();
        savedMatrix = new Matrix();
        start = new PointF();
        mid = new PointF();

        // 初始化模式
        mode = MODE_NONE;

        // 设置图片资源
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mylove);
        bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
        setImageBitmap(bitmap);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {

            case MotionEvent.ACTION_DOWN:// 单点接触屏幕时
                savedMatrix.set(currentMatrix);
                start.set(event.getX(), event.getY());
                mode = MODE_DRAG;
                preEventCoor = null;
                break;

            case MotionEvent.ACTION_POINTER_DOWN: // 第二个点接触屏幕时
                preMove = calSpacing(event);
                if (preMove > 10F) {
                    savedMatrix.set(currentMatrix);
                    calMidPoint(mid, event);
                    mode = MODE_ZOOM;
                }

                preEventCoor = new float[4];
                preEventCoor[0] = event.getX(0);
                preEventCoor[1] = event.getX(1);
                preEventCoor[2] = event.getY(0);
                preEventCoor[3] = event.getY(1);
                saveRotate = calRotation(event);

                break;

            case MotionEvent.ACTION_UP:// 单点厉害屏幕时
            case MotionEvent.ACTION_POINTER_UP: // 第二个点离开屏幕时
                mode = MODE_NONE;
                preEventCoor = null;
                break;

            case MotionEvent.ACTION_MOVE: // 触摸点移动时
                // 单点触控拖拽平移
                if (mode == MODE_DRAG) {
                    currentMatrix.set(savedMatrix);
                    float dx = event.getX() - start.x;
                    float dy = event.getY() - start.y;
                    currentMatrix.postTranslate(dx, dy);

                } else if (mode == MODE_ZOOM && event.getPointerCount() == 2) { // 两点触控拖放旋转
                    float currentMove = calSpacing(event);
                    currentMatrix.set(savedMatrix);
                    // 指尖移动距离大于10F缩放
                    if (currentMove > 10F) {
                        float scale = currentMove / preMove;
                        currentMatrix.postScale(scale, scale, mid.x, mid.y);
                    }

                    // 保持两点时旋转
                    if (preEventCoor != null) {
                        rotate = calRotation(event);
                        float r = rotate - saveRotate;
                        currentMatrix.postRotate(r, getMeasuredWidth() / 2, getMeasuredHeight() / 2);
                    }

                }

                break;

        }

        setImageMatrix(currentMatrix);

        return true;
    }

    /**
     * 计算旋转角度
     * @param event
     * @return
     */
    private float calRotation(MotionEvent event) {

        double deltaX = event.getX(0) - event.getX(1);
        double deltaY = event.getX(0) - event.getY(1);
        double radius = Math.atan2(deltaY, deltaX);
        return (float) Math.toDegrees(radius);
    }

    /**
     * 计算两个触摸点的中点坐标
     * @param point
     * @param event
     */
    private void calMidPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }

    /**
     * 计算两个触摸点间的距离
     * @param event
     * @return
     */
    private float calSpacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);

    }
}
